package util;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.servlet.http.HttpServletRequest;

import net.sf.json.JSONException;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import util.http.IPUtils;

import com.bigdatan.b2c.entity.pojo.Token;
import com.bigdatan.b2c.entity.wx.ParamMapKeyNames;

/**
 * @ClassName: CommonUtil
 * @Description: 通用工具类
 * @author liukz【525015102@qq.com】
 * @date 2015-4-26 上午12:44:51
 * 
 */
public class CommonUtil {
	private static Logger log = LoggerFactory.getLogger(CommonUtil.class);

	// 凭证获取（GET）
	public final static String token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
	private static String DATE_FORMAT_STR = "yyyyMMddHHmmss";

	/**
	 * 发送https请求
	 * 
	 * @param requestUrl 请求地址
	 * @param requestMethod 请求方式（GET、POST）
	 * @param outputStr 提交的数据
	 * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
	 */
	public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
		JSONObject jsonObject = null;
		try {
			// 创建SSLContext对象，并使用我们指定的信任管理器初始化
			TrustManager[] tm = { new MyX509TrustManager() };
			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
			sslContext.init(null, tm, new java.security.SecureRandom());
			// 从上述SSLContext对象中得到SSLSocketFactory对象
			SSLSocketFactory ssf = sslContext.getSocketFactory();

			URL url = new URL(requestUrl);
			HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
			conn.setSSLSocketFactory(ssf);

			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setUseCaches(false);
			// 设置请求方式（GET/POST）
			conn.setRequestMethod(requestMethod);

			// 当outputStr不为null时向输出流写数据
			if (null != outputStr) {
				OutputStream outputStream = conn.getOutputStream();
				// 注意编码格式
				outputStream.write(outputStr.getBytes("UTF-8"));
				outputStream.close();
			}

			// 从输入流读取返回内容
			InputStream inputStream = conn.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
			BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
			String str = null;
			StringBuffer buffer = new StringBuffer();
			while ((str = bufferedReader.readLine()) != null) {
				buffer.append(str);
			}

			// 释放资源
			bufferedReader.close();
			inputStreamReader.close();
			inputStream.close();
			inputStream = null;
			conn.disconnect();
			jsonObject = JSONObject.fromObject(buffer.toString());
		} catch (ConnectException ce) {
			log.error("连接超时：{}", ce);
		} catch (Exception e) {
			log.error("https请求异常：{}", e);
		}
		return jsonObject;
	}

	/**
	 * 获取接口访问凭证
	 * 
	 * @param appid 凭证
	 * @param appsecret 密钥
	 * @return
	 */
	public static Token getToken(String appid, String appsecret) {
		Token token = null;
		String requestUrl = token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
		// 发起GET请求获取凭证
		JSONObject jsonObject = httpsRequest(requestUrl, "GET", null);

		if (null != jsonObject) {
			try {
				token = new Token();
				token.setAccessToken(jsonObject.getString("access_token"));
				token.setExpiresIn(jsonObject.getInt("expires_in"));
			} catch (JSONException e) {
				token = null;
				// 获取token失败
				log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"),
						jsonObject.getString("errmsg"));
			}
		}
		return token;
	}

	/**
	 * URL编码（utf-8）
	 * 
	 * @param source
	 * @return
	 */
	public static String urlEncodeUTF8(String source) {
		String result = source;
		try {
			result = java.net.URLEncoder.encode(source, "utf-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 根据内容类型判断文件扩展名
	 * 
	 * @param contentType 内容类型
	 * @return
	 */
	public static String getFileExt(String contentType) {
		String fileExt = "";
		if ("image/jpeg".equals(contentType))
			fileExt = ".jpg";
		else if ("audio/mpeg".equals(contentType))
			fileExt = ".mp3";
		else if ("audio/amr".equals(contentType))
			fileExt = ".amr";
		else if ("video/mp4".equals(contentType))
			fileExt = ".mp4";
		else if ("video/mpeg4".equals(contentType))
			fileExt = ".mp4";
		return fileExt;
	}

	/**
	 * 获取请求头，并将javaScript过滤转义
	 * 
	 * @param request
	 * @param headName
	 * @return
	 */
	public static String getRequestHead(HttpServletRequest request, String headName) {
		String headStr = null;
		if (null != request) {
			headStr = request.getHeader(headName);
			if (StringUtils.isNotEmpty(headStr)) {
				headStr = StringEscapeUtils.escapeJavaScript(headStr);
			}
		}
		return headStr;
	}

	/**
	 * 从request对象中获取所有对象，并获取跳转前地址和客户IP
	 * 
	 * @param request
	 * @return
	 */
	public static Map<String, String> getRequestParams(HttpServletRequest request) {
		Map<String, String> paramsMap = new HashMap<String, String>();

		// 从request获取跳转前地址和客户IP
		String request_url = getRequestHead(request, "Referer");
		String customerIp = IPUtils.getClientIP(request);
		paramsMap.put(ParamMapKeyNames.REFER, request_url);
		paramsMap.put(ParamMapKeyNames.CLIENT_IP, customerIp);

		// 循环获取所有参数
		Enumeration<?> attNames = request.getParameterNames();
		while (attNames.hasMoreElements()) {
			String attName = (String) attNames.nextElement();
			paramsMap.put(attName, request.getParameter(attName));
		}
		return paramsMap;
	}

	/**
	 * 从request对象中获取所有对象，并获取跳转前地址和客户IP
	 * 
	 * @param request
	 * @return
	 */
	public static Map<String, Object> getRequestAttributes(HttpServletRequest request) {
		Map<String, Object> paramsMap = new HashMap<String, Object>();

		// 从request获取跳转前地址和客户IP
		String request_url = getRequestHead(request, "Referer");
		String customerIp = IPUtils.getClientIP(request);
		paramsMap.put("request_url", request_url);
		paramsMap.put("customerIp", customerIp);

		// 循环获取所有参数
		Enumeration<?> attNames = request.getAttributeNames();
		while (attNames.hasMoreElements()) {
			String attName = (String) attNames.nextElement();
			paramsMap.put(attName, request.getAttribute(attName));
		}
		return paramsMap;
	}

	/**
	 * 检查是否url
	 * 
	 * @param str
	 * @return
	 */
	public static boolean chckIsUrl(String str) {
		String regex = "http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?";
		Pattern p = Pattern.compile(regex);
		Matcher m = p.matcher(str);
		boolean b = m.matches();
		return b;
	}

	/**
	 * 检查是否IP
	 * 
	 * @param str
	 * @return
	 */
	public static boolean checkIsIp(String str) {
		Pattern pattern = Pattern
				.compile("\\b((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\.((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\.((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\.((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\b");
		Matcher m = pattern.matcher(str);
		boolean b = m.matches();
		return b;
	}

	/**
	 * 检查金额格式 ： 形如“xxx.xx”，其中xx全为数字
	 * 
	 * @param orderAmount
	 * @return
	 */
	public static boolean checkAmount(String orderAmount) {
		Pattern p = Pattern.compile("^(([1-9]\\d*)|([0]))(\\.\\d{1,2})?$");
		Matcher m = p.matcher(orderAmount);
		return m.matches();
	}

	/**
	 * 判断字符串内容是否是数字
	 * 
	 * @param str
	 * @return
	 */
	public static boolean checkIsNumeric(String str) {
		for (int i = str.length(); --i >= 0;) {
			if (!Character.isDigit(str.charAt(i))) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 检查手机号是否正确
	 * 
	 * @param StrMobileNo
	 * @return
	 */
	public static boolean mobileNoValidate(String StrMobileNo) {
		boolean b = true;
		if (StringUtils.isEmpty(StrMobileNo)) {
			b = false;
			return b;
		}
		StrMobileNo = StrMobileNo.trim();
		Pattern pattern = Pattern
				.compile("^((13[4-9])|(147)|(15[0-2,7-9])|(18[2-3,7-8])|(13[0-2])|(145)|(15[5-6])|(186)|(133)|(153)|(18[0,9]))\\d{8}$");
		Matcher m = pattern.matcher(StrMobileNo);
		b = m.matches();
		return b;
	}

	/**
	 * 检查参数是否为空
	 * 
	 * @param str 需要检查的参数
	 * @return
	 */
	public static boolean checkBlank(String str) {
		boolean result = true;
		if (null == str || "".equals(str) || "".equals(str.trim())) {
			result = false;
		}
		return result;
	}

	/**
	 * 检查字符串长度
	 * 
	 * @param str 需校验的字符串
	 * 
	 * @param mixLength 最小长度
	 * @param mixLength 最大长度
	 * @return
	 */
	public static boolean checkLength(String str, int mixLength, int maxLength) {
		boolean result = true;
		if (str.length() > maxLength || str.length() < mixLength) {
			result = false;
		}
		return result;
	}

	/**
	 * 检查字符串长度
	 * 
	 * @param str 需校验的字符串
	 * @param mixLength 最大长度
	 * @return
	 */
	public static boolean checkLength(String str, int maxLength) {
		return checkLength(str, 0, maxLength);
	}

	/**
	 * 检查字符串是否为日期
	 * 
	 * @param str
	 * @return
	 */
	public static boolean checkIsDate(String str) {
		boolean result = false;
		SimpleDateFormat sd = new SimpleDateFormat(DATE_FORMAT_STR);
		try {
			sd.parse(str);
			result = true;
		} catch (ParseException e) {
			result = false;
		}
		return result;
	}

	public static String convertServiceProvider(String serviceProviderName) {
		if (serviceProviderName.contains("联通")) {
			return "联通";
		} else if (serviceProviderName.contains("移动")) {
			return "移动";
		} else if (serviceProviderName.contains("电信")) {
			return "电信";
		}
		return "";
	}

	
}